# -*- encoding: utf-8 -*-
import datetime

from google.appengine.ext import db

from django import forms
from django.utils.translation import ugettext as _

from metrics.models import MetricsView, IntegerProperty, properties
from metrics.forms import UniversalFloatField

class UserMetricsView(MetricsView):
    """The metrics view related with the users"""

class Weight(IntegerProperty):
    """Property for storing the weight of the day"""
    # The weight is stored in gram. However, the interface present
    # units more familiar for the user (kg, lbs, etc).
    MIN_VALUE = 3
    MAX_VALUE = 200

    @classmethod
    def display(cls, value):
        value = float(value)/1000
        return "%g kg" % value

    @classmethod
    def get_form(cls, data=None):
        class WeightForm(forms.Form):
            value = UniversalFloatField(label=_(u'Weight'),
                                        required=False,
                                        min_value=cls.MIN_VALUE,
                                        max_value=cls.MAX_VALUE,
                                        help_text=_(u'in kilogram'))
        return WeightForm(data, prefix='weight')

    @classmethod
    def _update_grapher(cls, grapher, user):
        def round_value(value, low=False, div=5000):
            if low:
                value -= div
            remainder = value % div
            return value + div - remainder

        grapher.display_data_func = cls.display
        userparameters = UserParameters.gql('WHERE user = :1', user).get()
        min_value = round_value(min(grapher.values), True)
        max_value = round_value(max(grapher.values))

        bmi_levels = ''
        if userparameters:
            if userparameters.size:
                size_param = (userparameters.size)**2
                min_bmi = float(20 * size_param) / 1000
                max_bmi = min_bmi*25/20
                if min_bmi < min_value:
                    min_value = round_value(min_bmi, True)

                if max_bmi > max_value:
                    max_value = round_value(max_bmi)
                span = max_value - min_value
                min_level = float(min_bmi - min_value) / span
                max_level = float(max_bmi - min_value) / span                

                bmi_levels = ('r,E5F9EC,0,%s,%s|' % (min_level, max_level))
        grapher.extra = '&chm=%sB,76A4FB,0,0,0' % bmi_levels
        grapher.min_value = min_value
        grapher.max_value = max_value
        return grapher

    @classmethod
    def add_data(cls, user, date, metrics_view, data):
        valid = False
        form = cls.get_form(data)
        if form.is_valid():
            value = form.cleaned_data['value']
            if not value:
                valid = True
            else:
                int_value = int(value*1000)
                instance = cls(user=user,
                               date=date,
                               metrics_view=metrics_view,
                               value=int_value)
                instance.put()
                valid = True
        return valid, form

class UserParameters(db.Model):
    MIN_SIZE = 1
    MAX_SIZE = 2.36
    user = db.UserProperty(required=True)

    # Millimeter because cm is simply too error prone
    size = db.IntegerProperty(_(u"Size in millimeter"),
                              required=False)

    birthdate = db.DateProperty(_(u"Date of birth"),
                                required=False)

    def get_form(self, data=None):
        initial_size = initial_birthdate = ''
        if self.size:
            initial_size=float(self.size)/1000
        if self.birthdate:
            initial_birthdate = self.birthdate.strftime('%d/%m/%Y')

        class ParametersForm(forms.Form):
            size = UniversalFloatField(label=_(u'Size'),
                                       required=False,
                                       min_value=self.MIN_SIZE,
                                       max_value=self.MAX_SIZE,
                                       help_text=_(u'in meter'), 
                                       initial=initial_size)
            birthdate = forms.DateField(label=_(u'Date of birth'),
                                        required=False,
                                        input_formats=('%d/%m/%Y', '%d/%m/%y'),
                                        help_text=_(u"e.g. 20/10/1984"), 
                                        initial=initial_birthdate)
            def clean_birthdate(self):
                date = self.cleaned_data['birthdate']
                today = datetime.date.today()
                dayspan = (today - date).days

                if dayspan < 0:
                    raise forms.ValidationError(_(u"Birthday in the future"))
                elif dayspan < 3650: # ten years:
                    raise forms.ValidationError(_(u"Come on, you are older than that"))
                return date
        return ParametersForm(data, prefix='parameters')

    def set_data(self, data):
        form = self.get_form(data)
        valid = False
        if form.is_valid():
            data = form.cleaned_data
            size = data.get('size', None)
            if size:
                self.size = int(size * 1000)
            else:
                self.size = None
            date = repr(data['birthdate'])
            self.birthdate = data.get('birthdate', None)

            self.put()
            valid = True
        return valid, form
